home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / libg_261.zip / libg_261 / libg++ / src / String.h < prev    next >
C/C++ Source or Header  |  1994-10-12  |  34KB  |  1,283 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /* 
  3. Copyright (C) 1988 Free Software Foundation
  4.     written by Doug Lea (dl@rocky.oswego.edu)
  5.  
  6. This file is part of the GNU C++ Library.  This library is free
  7. software; you can redistribute it and/or modify it under the terms of
  8. the GNU Library General Public License as published by the Free
  9. Software Foundation; either version 2 of the License, or (at your
  10. option) any later version.  This library is distributed in the hope
  11. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  12. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13. PURPOSE.  See the GNU Library General Public License for more details.
  14. You should have received a copy of the GNU Library General Public
  15. License along with this library; if not, write to the Free Software
  16. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19.  
  20. #ifndef _String_h
  21. #ifdef __GNUG__
  22. #pragma interface
  23. #endif
  24. #define _String_h 1
  25.  
  26. #include <iostream.h>
  27. #include <Regex.h>
  28.  
  29. struct StrRep                     // internal String representations
  30. {
  31.   unsigned short    len;         // string length 
  32.   unsigned short    sz;          // allocated space
  33.   char              s[1];        // the string starts here 
  34.                                  // (at least 1 char for trailing null)
  35.                                  // allocated & expanded via non-public fcts
  36. };
  37.  
  38. // primitive ops on StrReps -- nearly all String fns go through these.
  39.  
  40. StrRep*     Salloc(StrRep*, const char*, int, int);
  41. StrRep*     Scopy(StrRep*, const StrRep*);
  42. StrRep*     Scat(StrRep*, const char*, int, const char*, int);
  43. StrRep*     Scat(StrRep*, const char*, int,const char*,int, const char*,int);
  44. StrRep*     Sprepend(StrRep*, const char*, int);
  45. StrRep*     Sreverse(const StrRep*, StrRep*);
  46. StrRep*     Supcase(const StrRep*, StrRep*);
  47. StrRep*     Sdowncase(const StrRep*, StrRep*);
  48. StrRep*     Scapitalize(const StrRep*, StrRep*);
  49.  
  50. // These classes need to be defined in the order given
  51.  
  52. class String;
  53. class SubString;
  54.  
  55. class SubString
  56. {
  57.   friend class      String;
  58. protected:
  59.  
  60.   String&           S;        // The String I'm a substring of
  61.   unsigned short    pos;      // starting position in S's rep
  62.   unsigned short    len;      // length of substring
  63.  
  64.   void              assign(const StrRep*, const char*, int = -1);
  65.                     SubString(String& x, int p, int l);
  66.                     SubString(const SubString& x);
  67.  
  68. public:
  69.  
  70. // Note there are no public constructors. SubStrings are always
  71. // created via String operations
  72.  
  73.                    ~SubString();
  74.  
  75.   SubString&        operator =  (const String&     y);
  76.   SubString&        operator =  (const SubString&  y);
  77.   SubString&        operator =  (const char* t);
  78.   SubString&        operator =  (char        c);
  79.  
  80. // return 1 if target appears anywhere in SubString; else 0
  81.  
  82.   int               contains(char        c) const;
  83.   int               contains(const String&     y) const;
  84.   int               contains(const SubString&  y) const;
  85.   int               contains(const char* t) const;
  86.   int               contains(const Regex&       r) const;
  87.  
  88. // return 1 if target matches entire SubString
  89.  
  90.   int               matches(const Regex&  r) const;
  91.  
  92. // IO 
  93.  
  94.   friend ostream&   operator<<(ostream& s, const SubString& x);
  95.  
  96. // status
  97.  
  98.   unsigned int      length() const;
  99.   int               empty() const;
  100.   const char*       chars() const;
  101.  
  102.   int               OK() const; 
  103.  
  104. };
  105.  
  106.  
  107. class String
  108. {
  109.   friend class      SubString;
  110.  
  111. protected:
  112.   StrRep*           rep;   // Strings are pointers to their representations
  113.  
  114. // some helper functions
  115.  
  116.   int               search(int, int, const char*, int = -1) const;
  117.   int               search(int, int, char) const;
  118.   int               match(int, int, int, const char*, int = -1) const;
  119.   int               _gsub(const char*, int, const char* ,int);
  120.   int               _gsub(const Regex&, const char*, int);
  121.   SubString         _substr(int, int);
  122.  
  123. public:
  124.  
  125. // constructors & assignment
  126.  
  127.                     String();
  128.                     String(const String& x);
  129.                     String(const SubString&  x);
  130.                     String(const char* t);
  131.                     String(const char* t, int len);
  132.                     String(char c);
  133.  
  134.                     ~String();
  135.  
  136.   String&           operator =  (const String&     y);
  137.   String&           operator =  (const char* y);
  138.   String&           operator =  (char        c);
  139.   String&           operator =  (const SubString&  y);
  140.  
  141. // concatenation
  142.  
  143.   String&           operator += (const String&     y); 
  144.   String&           operator += (const SubString&  y);
  145.   String&           operator += (const char* t);
  146.   String&           operator += (char        c);
  147.  
  148.   void              prepend(const String&     y); 
  149.   void              prepend(const SubString&  y);
  150.   void              prepend(const char* t);
  151.   void              prepend(char        c);
  152.  
  153.  
  154. // procedural versions:
  155. // concatenate first 2 args, store result in last arg
  156.  
  157.   friend inline void     cat(const String&, const String&, String&);
  158.   friend inline void     cat(const String&, const SubString&, String&);
  159.   friend inline void     cat(const String&, const char*, String&);
  160.   friend inline void     cat(const String&, char, String&);
  161.  
  162.   friend inline void     cat(const SubString&, const String&, String&);
  163.   friend inline void     cat(const SubString&, const SubString&, String&);
  164.   friend inline void     cat(const SubString&, const char*, String&);
  165.   friend inline void     cat(const SubString&, char, String&);
  166.  
  167.   friend inline void     cat(const char*, const String&, String&);
  168.   friend inline void     cat(const char*, const SubString&, String&);
  169.   friend inline void     cat(const char*, const char*, String&);
  170.   friend inline void     cat(const char*, char, String&);
  171.  
  172. // double concatenation, by request. (yes, there are too many versions, 
  173. // but if one is supported, then the others should be too...)
  174. // Concatenate first 3 args, store in last arg
  175.  
  176.   friend inline void     cat(const String&,const String&, const String&,String&);
  177.   friend inline void     cat(const String&,const String&,const SubString&,String&);
  178.   friend inline void     cat(const String&,const String&, const char*, String&);
  179.   friend inline void     cat(const String&,const String&, char, String&);
  180.   friend inline void     cat(const String&,const SubString&,const String&,String&);
  181.   inline friend void     cat(const String&,const SubString&,const SubString&,String&);
  182.   friend inline void     cat(const String&,const SubString&, const char*, String&);
  183.   friend inline void     cat(const String&,const SubString&, char, String&);
  184.   friend inline void     cat(const String&,const char*, const String&,    String&);
  185.   friend inline void     cat(const String&,const char*, const SubString&, String&);
  186.   friend inline void     cat(const String&,const char*, const char*, String&);
  187.   friend inline void     cat(const String&,const char*, char, String&);
  188.  
  189.   friend inline void     cat(const char*, const String&, const String&,String&);
  190.   friend inline void     cat(const char*,const String&,const SubString&,String&);
  191.   friend inline void     cat(const char*,const String&, const char*, String&);
  192.   friend inline void     cat(const char*,const String&, char, String&);
  193.   friend inline void     cat(const char*,const SubString&,const String&,String&);
  194.   friend inline void     cat(const char*,const SubString&,const SubString&,String&);
  195.   friend inline void     cat(const char*,const SubString&, const char*, String&);
  196.   friend inline void     cat(const char*,const SubString&, char, String&);
  197.   friend inline void     cat(const char*,const char*, const String&,    String&);
  198.   friend inline void     cat(const char*,const char*, const SubString&, String&);
  199.   friend inline void     cat(const char*,const char*, const char*, String&);
  200.   friend inline void     cat(const char*,const char*, char, String&);
  201.  
  202.  
  203. // searching & matching
  204.  
  205. // return position of target in string or -1 for failure
  206.  
  207.   int               index(char        c, int startpos = 0) const;      
  208.   int               index(const String&     y, int startpos = 0) const;      
  209.   int               index(const SubString&  y, int startpos = 0) const;      
  210.   int               index(const char* t, int startpos = 0) const;  
  211.   int               index(const Regex&      r, int startpos = 0) const;       
  212.  
  213. // return 1 if target appears anyhere in String; else 0
  214.  
  215.   int               contains(char        c) const;
  216.   int               contains(const String&     y) const;
  217.   int               contains(const SubString&  y) const;
  218.   int               contains(const char* t) const;
  219.   int               contains(const Regex&      r) const;
  220.  
  221. // return 1 if target appears anywhere after position pos 
  222. // (or before, if pos is negative) in String; else 0
  223.  
  224.   int               contains(char        c, int pos) const;
  225.   int               contains(const String&     y, int pos) const;
  226.   int               contains(const SubString&  y, int pos) const;
  227.   int               contains(const char* t, int pos) const;
  228.   int               contains(const Regex&      r, int pos) const;
  229.  
  230. // return 1 if target appears at position pos in String; else 0
  231.  
  232.   int               matches(char        c, int pos = 0) const;
  233.   int               matches(const String&     y, int pos = 0) const;
  234.   int               matches(const SubString&  y, int pos = 0) const;
  235.   int               matches(const char* t, int pos = 0) const;
  236.   int               matches(const Regex&      r, int pos = 0) const;
  237.  
  238. //  return number of occurences of target in String
  239.  
  240.   int               freq(char        c) const; 
  241.   int               freq(const String&     y) const;
  242.   int               freq(const SubString&  y) const;
  243.   int               freq(const char* t) const;
  244.  
  245. // SubString extraction
  246.  
  247. // Note that you can't take a substring of a const String, since
  248. // this leaves open the possiblility of indirectly modifying the
  249. // String through the SubString
  250.  
  251.   SubString         at(int         pos, int len);
  252.   SubString         operator () (int         pos, int len); // synonym for at
  253.  
  254.   SubString         at(const String&     x, int startpos = 0); 
  255.   SubString         at(const SubString&  x, int startpos = 0); 
  256.   SubString         at(const char* t, int startpos = 0);
  257.   SubString         at(char        c, int startpos = 0);
  258.   SubString         at(const Regex&      r, int startpos = 0); 
  259.  
  260.   SubString         before(int          pos);
  261.   SubString         before(const String&      x, int startpos = 0);
  262.   SubString         before(const SubString&   x, int startpos = 0);
  263.   SubString         before(const char*  t, int startpos = 0);
  264.   SubString         before(char         c, int startpos = 0);
  265.   SubString         before(const Regex&       r, int startpos = 0);
  266.  
  267.   SubString         through(int          pos);
  268.   SubString         through(const String&      x, int startpos = 0);
  269.   SubString         through(const SubString&   x, int startpos = 0);
  270.   SubString         through(const char*  t, int startpos = 0);
  271.   SubString         through(char         c, int startpos = 0);
  272.   SubString         through(const Regex&       r, int startpos = 0);
  273.  
  274.   SubString         from(int          pos);
  275.   SubString         from(const String&      x, int startpos = 0);
  276.   SubString         from(const SubString&   x, int startpos = 0);
  277.   SubString         from(const char*  t, int startpos = 0);
  278.   SubString         from(char         c, int startpos = 0);
  279.   SubString         from(const Regex&       r, int startpos = 0);
  280.  
  281.   SubString         after(int         pos);
  282.   SubString         after(const String&     x, int startpos = 0);
  283.   SubString         after(const SubString&  x, int startpos = 0);
  284.   SubString         after(const char* t, int startpos = 0);
  285.   SubString         after(char        c, int startpos = 0);
  286.   SubString         after(const Regex&      r, int startpos = 0);
  287.  
  288.  
  289. // deletion
  290.  
  291. // delete len chars starting at pos
  292.   void              del(int         pos, int len);
  293.  
  294. // delete the first occurrence of target after startpos
  295.  
  296.   void              del(const String&     y, int startpos = 0);
  297.   void              del(const SubString&  y, int startpos = 0);
  298.   void              del(const char* t, int startpos = 0);
  299.   void              del(char        c, int startpos = 0);
  300.   void              del(const Regex&      r, int startpos = 0);
  301.  
  302. // global substitution: substitute all occurrences of pat with repl
  303.  
  304.   int               gsub(const String&     pat, const String&     repl);
  305.   int               gsub(const SubString&  pat, const String&     repl);
  306.   int               gsub(const char* pat, const String&     repl);
  307.   int               gsub(const char* pat, const char* repl);
  308.   int               gsub(const Regex&      pat, const String&     repl);
  309.  
  310. // friends & utilities
  311.  
  312. // split string into array res at separators; return number of elements
  313.  
  314.   friend int        split(const String& x, String res[], int maxn, 
  315.                           const String& sep);
  316.   friend int        split(const String& x, String res[], int maxn, 
  317.                           const Regex&  sep);
  318.  
  319.   friend String     common_prefix(const String& x, const String& y, 
  320.                                   int startpos = 0);
  321.   friend String     common_suffix(const String& x, const String& y, 
  322.                                   int startpos = -1);
  323.   friend String     replicate(char        c, int n);
  324.   friend String     replicate(const String&     y, int n);
  325.   friend String     join(String src[], int n, const String& sep);
  326.  
  327. // simple builtin transformations
  328.  
  329.   friend inline String     reverse(const String& x);
  330.   friend inline String     upcase(const String& x);
  331.   friend inline String     downcase(const String& x);
  332.   friend inline String     capitalize(const String& x);
  333.  
  334. // in-place versions of above
  335.  
  336.   void              reverse();
  337.   void              upcase();
  338.   void              downcase();
  339.   void              capitalize();
  340.  
  341. // element extraction
  342.  
  343.   char&             operator [] (int i);
  344.   const char&       operator [] (int i) const;
  345.   char              elem(int i) const;
  346.   char              firstchar() const;
  347.   char              lastchar() const;
  348.  
  349. // conversion
  350.  
  351.                     operator const char*() const;
  352.   const char*       chars() const;
  353.  
  354.  
  355. // IO
  356.  
  357.   friend inline ostream&   operator<<(ostream& s, const String& x);
  358.   friend ostream&   operator<<(ostream& s, const SubString& x);
  359.   friend istream&   operator>>(istream& s, String& x);
  360.  
  361.   friend int        readline(istream& s, String& x, 
  362.                              char terminator = '\n',
  363.                              int discard_terminator = 1);
  364.  
  365. // status
  366.  
  367.   unsigned int      length() const;
  368.   int               empty() const;
  369.  
  370. // preallocate some space for String
  371.   void              alloc(int newsize);
  372.  
  373. // report current allocation (not length!)
  374.  
  375.   int               allocation() const;
  376.  
  377.  
  378.   void     error(const char* msg) const;
  379.  
  380.   int               OK() const;
  381. };
  382.  
  383. typedef String StrTmp; // for backward compatibility
  384.  
  385. // other externs
  386.  
  387. int        compare(const String&    x, const String&     y);
  388. int        compare(const String&    x, const SubString&  y);
  389. int        compare(const String&    x, const char* y);
  390. int        compare(const SubString& x, const String&     y);
  391. int        compare(const SubString& x, const SubString&  y);
  392. int        compare(const SubString& x, const char* y);
  393. int        fcompare(const String&   x, const String&     y); // ignore case
  394.  
  395. extern StrRep  _nilStrRep;
  396. extern String _nilString;
  397.  
  398. // status reports, needed before defining other things
  399.  
  400. inline unsigned int String::length() const {  return rep->len; }
  401. inline int         String::empty() const { return rep->len == 0; }
  402. inline const char* String::chars() const { return &(rep->s[0]); }
  403. inline int         String::allocation() const { return rep->sz; }
  404.  
  405. inline unsigned int SubString::length() const { return len; }
  406. inline int         SubString::empty() const { return len == 0; }
  407. inline const char* SubString::chars() const { return &(S.rep->s[pos]); }
  408.  
  409.  
  410. // constructors
  411.  
  412. inline String::String() 
  413.   : rep(&_nilStrRep) {}
  414. inline String::String(const String& x) 
  415.   : rep(Scopy(0, x.rep)) {}
  416. inline String::String(const char* t) 
  417.   : rep(Salloc(0, t, -1, -1)) {}
  418. inline String::String(const char* t, int tlen)
  419.   : rep(Salloc(0, t, tlen, tlen)) {}
  420. inline String::String(const SubString& y)
  421.   : rep(Salloc(0, y.chars(), y.length(), y.length())) {}
  422. inline String::String(char c) 
  423.   : rep(Salloc(0, &c, 1, 1)) {}
  424.  
  425. inline String::~String() { if (rep != &_nilStrRep) delete rep; }
  426.  
  427. inline SubString::SubString(const SubString& x)
  428.   :S(x.S), pos(x.pos), len(x.len) {}
  429. inline SubString::SubString(String& x, int first, int l)
  430.   :S(x), pos(first), len(l) {}
  431.  
  432. inline SubString::~SubString() {}
  433.  
  434. // assignment
  435.  
  436. inline String& String::operator =  (const String& y)
  437.   rep = Scopy(rep, y.rep);
  438.   return *this;
  439. }
  440.  
  441. inline String& String::operator=(const char* t)
  442. {
  443.   rep = Salloc(rep, t, -1, -1);
  444.   return *this;
  445. }
  446.  
  447. inline String& String::operator=(const SubString&  y)
  448. {
  449.   rep = Salloc(rep, y.chars(), y.length(), y.length());
  450.   return *this;
  451. }
  452.  
  453. inline String& String::operator=(char c)
  454. {
  455.   rep = Salloc(rep, &c, 1, 1);
  456.   return *this;
  457. }
  458.  
  459.  
  460. inline SubString& SubString::operator = (const char* ys)
  461. {
  462.   assign(0, ys);
  463.   return *this;
  464. }
  465.  
  466. inline SubString& SubString::operator = (char ch)
  467. {
  468.   assign(0, &ch, 1);
  469.   return *this;
  470. }
  471.  
  472. inline SubString& SubString::operator = (const String& y)
  473. {
  474.   assign(y.rep, y.chars(), y.length());
  475.   return *this;
  476. }
  477.  
  478. inline SubString& SubString::operator = (const SubString& y)
  479. {
  480.   assign(y.S.rep, y.chars(), y.length());
  481.   return *this;
  482. }
  483.  
  484. // Zillions of cats...
  485.  
  486. inline void cat(const String& x, const String& y, String& r)
  487. {
  488.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  489. }
  490.  
  491. inline void cat(const String& x, const SubString& y, String& r)
  492. {
  493.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  494. }
  495.  
  496. inline void cat(const String& x, const char* y, String& r)
  497. {
  498.   r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
  499. }
  500.  
  501. inline void cat(const String& x, char y, String& r)
  502. {
  503.   r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
  504. }
  505.  
  506. inline void cat(const SubString& x, const String& y, String& r)
  507. {
  508.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  509. }
  510.  
  511. inline void cat(const SubString& x, const SubString& y, String& r)
  512. {
  513.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  514. }
  515.  
  516. inline void cat(const SubString& x, const char* y, String& r)
  517. {
  518.   r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
  519. }
  520.  
  521. inline void cat(const SubString& x, char y, String& r)
  522. {
  523.   r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
  524. }
  525.  
  526. inline void cat(const char* x, const String& y, String& r)
  527. {
  528.   r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
  529. }
  530.  
  531. inline void cat(const char* x, const SubString& y, String& r)
  532. {
  533.   r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
  534. }
  535.  
  536. inline void cat(const char* x, const char* y, String& r)
  537. {
  538.   r.rep = Scat(r.rep, x, -1, y, -1);
  539. }
  540.  
  541. inline void cat(const char* x, char y, String& r)
  542. {
  543.   r.rep = Scat(r.rep, x, -1, &y, 1);
  544. }
  545.  
  546. inline void cat(const String& a, const String& x, const String& y, String& r)
  547. {
  548.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  549. }
  550.  
  551. inline void cat(const String& a, const String& x, const SubString& y, String& r)
  552. {
  553.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  554. }
  555.  
  556. inline void cat(const String& a, const String& x, const char* y, String& r)
  557. {
  558.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
  559. }
  560.  
  561. inline void cat(const String& a, const String& x, char y, String& r)
  562. {
  563.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
  564. }
  565.  
  566. inline void cat(const String& a, const SubString& x, const String& y, String& r)
  567. {
  568.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  569. }
  570.  
  571. inline void cat(const String& a, const SubString& x, const SubString& y, String& r)
  572. {
  573.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  574. }
  575.  
  576. inline void cat(const String& a, const SubString& x, const char* y, String& r)
  577. {
  578.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
  579. }
  580.  
  581. inline void cat(const String& a, const SubString& x, char y, String& r)
  582. {
  583.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
  584. }
  585.  
  586. inline void cat(const String& a, const char* x, const String& y, String& r)
  587. {
  588.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
  589. }
  590.  
  591. inline void cat(const String& a, const char* x, const SubString& y, String& r)
  592. {
  593.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
  594. }
  595.  
  596. inline void cat(const String& a, const char* x, const char* y, String& r)
  597. {
  598.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y, -1);
  599. }
  600.  
  601. inline void cat(const String& a, const char* x, char y, String& r)
  602. {
  603.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, &y, 1);
  604. }
  605.  
  606.  
  607. inline void cat(const char* a, const String& x, const String& y, String& r)
  608. {
  609.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  610. }
  611.  
  612. inline void cat(const char* a, const String& x, const SubString& y, String& r)
  613. {
  614.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  615. }
  616.  
  617. inline void cat(const char* a, const String& x, const char* y, String& r)
  618. {
  619.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
  620. }
  621.  
  622. inline void cat(const char* a, const String& x, char y, String& r)
  623. {
  624.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
  625. }
  626.  
  627. inline void cat(const char* a, const SubString& x, const String& y, String& r)
  628. {
  629.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  630. }
  631.  
  632. inline void cat(const char* a, const SubString& x, const SubString& y, String& r)
  633. {
  634.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  635. }
  636.  
  637. inline void cat(const char* a, const SubString& x, const char* y, String& r)
  638. {
  639.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
  640. }
  641.  
  642. inline void cat(const char* a, const SubString& x, char y, String& r)
  643. {
  644.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
  645. }
  646.  
  647. inline void cat(const char* a, const char* x, const String& y, String& r)
  648. {
  649.   r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
  650. }
  651.  
  652. inline void cat(const char* a, const char* x, const SubString& y, String& r)
  653. {
  654.   r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
  655. }
  656.  
  657. inline void cat(const char* a, const char* x, const char* y, String& r)
  658. {
  659.   r.rep = Scat(r.rep, a, -1, x, -1, y, -1);
  660. }
  661.  
  662. inline void cat(const char* a, const char* x, char y, String& r)
  663. {
  664.   r.rep = Scat(r.rep, a, -1, x, -1, &y, 1);
  665. }
  666.  
  667.  
  668. // operator versions
  669.  
  670. inline String& String::operator +=(const String& y)
  671. {
  672.   cat(*this, y, *this);
  673.   return *this;
  674. }
  675.  
  676. inline String& String::operator +=(const SubString& y)
  677. {
  678.   cat(*this, y, *this);
  679.   return *this;
  680. }
  681.  
  682. inline String& String::operator += (const char* y)
  683. {
  684.   cat(*this, y, *this);
  685.   return *this;
  686. }
  687.  
  688. inline String& String:: operator +=(char y)
  689. {
  690.   cat(*this, y, *this);
  691.   return *this;
  692. }
  693.  
  694. // constructive concatenation
  695.  
  696. #if defined(__GNUG__) && !defined(_G_NO_NRV)
  697.  
  698. inline String operator + (const String& x, const String& y) return r;
  699. {
  700.   cat(x, y, r);
  701. }
  702.  
  703. inline String operator + (const String& x, const SubString& y) return r;
  704. {
  705.   cat(x, y, r);
  706. }
  707.  
  708. inline String operator + (const String& x, const char* y) return r;
  709. {
  710.   cat(x, y, r);
  711. }
  712.  
  713. inline String operator + (const String& x, char y) return r;
  714. {
  715.   cat(x, y, r);
  716. }
  717.  
  718. inline String operator + (const SubString& x, const String& y) return r;
  719. {
  720.   cat(x, y, r);
  721. }
  722.  
  723. inline String operator + (const SubString& x, const SubString& y) return r;
  724. {
  725.   cat(x, y, r);
  726. }
  727.  
  728. inline String operator + (const SubString& x, const char* y) return r;
  729. {
  730.   cat(x, y, r);
  731. }
  732.  
  733. inline String operator + (const SubString& x, char y) return r;
  734. {
  735.   cat(x, y, r);
  736. }
  737.  
  738. inline String operator + (const char* x, const String& y) return r;
  739. {
  740.   cat(x, y, r);
  741. }
  742.  
  743. inline String operator + (const char* x, const SubString& y) return r;
  744. {
  745.   cat(x, y, r);
  746. }
  747.  
  748. inline String reverse(const String& x) return r;
  749. {
  750.   r.rep = Sreverse(x.rep, r.rep);
  751. }
  752.  
  753. inline String upcase(const String& x) return r;
  754. {
  755.   r.rep = Supcase(x.rep, r.rep);
  756. }
  757.  
  758. inline String downcase(const String& x) return r;
  759. {
  760.   r.rep = Sdowncase(x.rep, r.rep);
  761. }
  762.  
  763. inline String capitalize(const String& x) return r;
  764. {
  765.   r.rep = Scapitalize(x.rep, r.rep);
  766. }
  767.  
  768. #else /* NO_NRV */
  769.  
  770. inline String operator + (const String& x, const String& y)
  771. {
  772.   String r;  cat(x, y, r);  return r;
  773. }
  774.  
  775. inline String operator + (const String& x, const SubString& y) 
  776. {
  777.   String r; cat(x, y, r); return r;
  778. }
  779.  
  780. inline String operator + (const String& x, const char* y) 
  781. {
  782.   String r; cat(x, y, r); return r;
  783. }
  784.  
  785. inline String operator + (const String& x, char y) 
  786. {
  787.   String r; cat(x, y, r); return r;
  788. }
  789.  
  790. inline String operator + (const SubString& x, const String& y) 
  791. {
  792.   String r; cat(x, y, r); return r;
  793. }
  794.  
  795. inline String operator + (const SubString& x, const SubString& y) 
  796. {
  797.   String r; cat(x, y, r); return r;
  798. }
  799.  
  800. inline String operator + (const SubString& x, const char* y) 
  801. {
  802.   String r; cat(x, y, r); return r;
  803. }
  804.  
  805. inline String operator + (const SubString& x, char y) 
  806. {
  807.   String r; cat(x, y, r); return r;
  808. }
  809.  
  810. inline String operator + (const char* x, const String& y) 
  811. {
  812.   String r; cat(x, y, r); return r;
  813. }
  814.  
  815. inline String operator + (const char* x, const SubString& y) 
  816. {
  817.   String r; cat(x, y, r); return r;
  818. }
  819.  
  820. inline String reverse(const String& x) 
  821. {
  822.   String r; r.rep = Sreverse(x.rep, r.rep); return r;
  823. }
  824.  
  825. inline String upcase(const String& x) 
  826. {
  827.   String r; r.rep = Supcase(x.rep, r.rep); return r;
  828. }
  829.  
  830. inline String downcase(const String& x) 
  831. {
  832.   String r; r.rep = Sdowncase(x.rep, r.rep); return r;
  833. }
  834.  
  835. inline String capitalize(const String& x) 
  836. {
  837.   String r; r.rep = Scapitalize(x.rep, r.rep); return r;
  838. }
  839.  
  840. #endif
  841.  
  842. // prepend
  843.  
  844. inline void String::prepend(const String& y)
  845. {
  846.   rep = Sprepend(rep, y.chars(), y.length());
  847. }
  848.  
  849. inline void String::prepend(const char* y)
  850. {
  851.   rep = Sprepend(rep, y, -1); 
  852. }
  853.  
  854. inline void String::prepend(char y)
  855. {
  856.   rep = Sprepend(rep, &y, 1); 
  857. }
  858.  
  859. inline void String::prepend(const SubString& y)
  860. {
  861.   rep = Sprepend(rep, y.chars(), y.length());
  862. }
  863.  
  864. // misc transformations
  865.  
  866.  
  867. inline void String::reverse()
  868. {
  869.   rep = Sreverse(rep, rep);
  870. }
  871.  
  872.  
  873. inline void String::upcase()
  874. {
  875.   rep = Supcase(rep, rep);
  876. }
  877.  
  878.  
  879. inline void String::downcase()
  880. {
  881.   rep = Sdowncase(rep, rep);
  882. }
  883.  
  884.  
  885. inline void String::capitalize()
  886. {
  887.   rep = Scapitalize(rep, rep);
  888. }
  889.  
  890. // element extraction
  891.  
  892. inline char&  String::operator [] (int i) 
  893.   if (((unsigned)i) >= length()) error("invalid index");
  894.   return rep->s[i];
  895. }
  896.  
  897. inline const char&  String::operator [] (int i) const
  898.   if (((unsigned)i) >= length()) error("invalid index");
  899.   return rep->s[i];
  900. }
  901.  
  902. inline char  String::elem (int i) const
  903.   if (((unsigned)i) >= length()) error("invalid index");
  904.   return rep->s[i];
  905. }
  906.  
  907. inline char  String::firstchar() const
  908.   return elem(0);
  909. }
  910.  
  911. inline char  String::lastchar() const
  912.   return elem(length() - 1);
  913. }
  914.  
  915. // searching
  916.  
  917. inline int String::index(char c, int startpos) const
  918. {
  919.   return search(startpos, length(), c);
  920. }
  921.  
  922. inline int String::index(const char* t, int startpos) const
  923. {   
  924.   return search(startpos, length(), t);
  925. }
  926.  
  927. inline int String::index(const String& y, int startpos) const
  928. {   
  929.   return search(startpos, length(), y.chars(), y.length());
  930. }
  931.  
  932. inline int String::index(const SubString& y, int startpos) const
  933. {   
  934.   return search(startpos, length(), y.chars(), y.length());
  935. }
  936.  
  937. inline int String::index(const Regex& r, int startpos) const
  938. {
  939.   int unused;  return r.search(chars(), length(), unused, startpos);
  940. }
  941.  
  942. inline int String::contains(char c) const
  943. {
  944.   return search(0, length(), c) >= 0;
  945. }
  946.  
  947. inline int String::contains(const char* t) const
  948. {   
  949.   return search(0, length(), t) >= 0;
  950. }
  951.  
  952. inline int String::contains(const String& y) const
  953. {   
  954.   return search(0, length(), y.chars(), y.length()) >= 0;
  955. }
  956.  
  957. inline int String::contains(const SubString& y) const
  958. {   
  959.   return search(0, length(), y.chars(), y.length()) >= 0;
  960. }
  961.  
  962. inline int String::contains(char c, int p) const
  963. {
  964.   return match(p, length(), 0, &c, 1) >= 0;
  965. }
  966.  
  967. inline int String::contains(const char* t, int p) const
  968. {
  969.   return match(p, length(), 0, t) >= 0;
  970. }
  971.  
  972. inline int String::contains(const String& y, int p) const
  973. {
  974.   return match(p, length(), 0, y.chars(), y.length()) >= 0;
  975. }
  976.  
  977. inline int String::contains(const SubString& y, int p) const
  978. {
  979.   return match(p, length(), 0, y.chars(), y.length()) >= 0;
  980. }
  981.  
  982. inline int String::contains(const Regex& r) const
  983. {
  984.   int unused;  return r.search(chars(), length(), unused, 0) >= 0;
  985. }
  986.  
  987. inline int String::contains(const Regex& r, int p) const
  988. {
  989.   return r.match(chars(), length(), p) >= 0;
  990. }
  991.  
  992.  
  993. inline int String::matches(const SubString& y, int p) const
  994. {
  995.   return match(p, length(), 1, y.chars(), y.length()) >= 0;
  996. }
  997.  
  998. inline int String::matches(const String& y, int p) const
  999. {
  1000.   return match(p, length(), 1, y.chars(), y.length()) >= 0;
  1001. }
  1002.  
  1003. inline int String::matches(const char* t, int p) const
  1004. {
  1005.   return match(p, length(), 1, t) >= 0;
  1006. }
  1007.  
  1008. inline int String::matches(char c, int p) const
  1009. {
  1010.   return match(p, length(), 1, &c, 1) >= 0;
  1011. }
  1012.  
  1013. inline int String::matches(const Regex& r, int p) const
  1014. {
  1015.   int l = (p < 0)? -p : length() - p;
  1016.   return r.match(chars(), length(), p) == l;
  1017. }
  1018.  
  1019.  
  1020. inline int SubString::contains(const char* t) const
  1021. {   
  1022.   return S.search(pos, pos+len, t) >= 0;
  1023. }
  1024.  
  1025. inline int SubString::contains(const String& y) const
  1026. {   
  1027.   return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
  1028. }
  1029.  
  1030. inline int SubString::contains(const SubString&  y) const
  1031. {   
  1032.   return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
  1033. }
  1034.  
  1035. inline int SubString::contains(char c) const
  1036. {
  1037.   return S.search(pos, pos+len, c) >= 0;
  1038. }
  1039.  
  1040. inline int SubString::contains(const Regex& r) const
  1041. {
  1042.   int unused;  return r.search(chars(), len, unused, 0) >= 0;
  1043. }
  1044.  
  1045. inline int SubString::matches(const Regex& r) const
  1046. {
  1047.   return r.match(chars(), len, 0) == len;
  1048. }
  1049.  
  1050.  
  1051. inline int String::gsub(const String& pat, const String& r)
  1052. {
  1053.   return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
  1054. }
  1055.  
  1056. inline int String::gsub(const SubString&  pat, const String& r)
  1057. {
  1058.   return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
  1059. }
  1060.  
  1061. inline int String::gsub(const Regex& pat, const String& r)
  1062. {
  1063.   return _gsub(pat, r.chars(), r.length());
  1064. }
  1065.  
  1066. inline int String::gsub(const char* pat, const String& r)
  1067. {
  1068.   return _gsub(pat, -1, r.chars(), r.length());
  1069. }
  1070.  
  1071. inline int String::gsub(const char* pat, const char* r)
  1072. {
  1073.   return _gsub(pat, -1, r, -1);
  1074. }
  1075.  
  1076.  
  1077.  
  1078. inline  ostream& operator<<(ostream& s, const String& x)
  1079. {
  1080.    s << x.chars(); return s;
  1081. }
  1082.  
  1083. // a zillion comparison operators
  1084.  
  1085. inline int operator==(const String& x, const String& y) 
  1086. {
  1087.   return compare(x, y) == 0; 
  1088. }
  1089.  
  1090. inline int operator!=(const String& x, const String& y)
  1091. {
  1092.   return compare(x, y) != 0; 
  1093. }
  1094.  
  1095. inline int operator>(const String& x, const String& y)
  1096. {
  1097.   return compare(x, y) > 0; 
  1098. }
  1099.  
  1100. inline int operator>=(const String& x, const String& y)
  1101. {
  1102.   return compare(x, y) >= 0; 
  1103. }
  1104.  
  1105. inline int operator<(const String& x, const String& y)
  1106. {
  1107.   return compare(x, y) < 0; 
  1108. }
  1109.  
  1110. inline int operator<=(const String& x, const String& y)
  1111. {
  1112.   return compare(x, y) <= 0; 
  1113. }
  1114.  
  1115. inline int operator==(const String& x, const SubString&  y) 
  1116. {
  1117.   return compare(x, y) == 0; 
  1118. }
  1119.  
  1120. inline int operator!=(const String& x, const SubString&  y)
  1121. {
  1122.   return compare(x, y) != 0; 
  1123. }
  1124.  
  1125. inline int operator>(const String& x, const SubString&  y)      
  1126. {
  1127.   return compare(x, y) > 0; 
  1128. }
  1129.  
  1130. inline int operator>=(const String& x, const SubString&  y)
  1131. {
  1132.   return compare(x, y) >= 0; 
  1133. }
  1134.  
  1135. inline int operator<(const String& x, const SubString&  y) 
  1136. {
  1137.   return compare(x, y) < 0; 
  1138. }
  1139.  
  1140. inline int operator<=(const String& x, const SubString&  y)
  1141. {
  1142.   return compare(x, y) <= 0; 
  1143. }
  1144.  
  1145. inline int operator==(const String& x, const char* t) 
  1146. {
  1147.   return compare(x, t) == 0; 
  1148. }
  1149.  
  1150. inline int operator!=(const String& x, const char* t) 
  1151. {
  1152.   return compare(x, t) != 0; 
  1153. }
  1154.  
  1155. inline int operator>(const String& x, const char* t)  
  1156. {
  1157.   return compare(x, t) > 0; 
  1158. }
  1159.  
  1160. inline int operator>=(const String& x, const char* t) 
  1161. {
  1162.   return compare(x, t) >= 0; 
  1163. }
  1164.  
  1165. inline int operator<(const String& x, const char* t)  
  1166. {
  1167.   return compare(x, t) < 0; 
  1168. }
  1169.  
  1170. inline int operator<=(const String& x, const char* t) 
  1171. {
  1172.   return compare(x, t) <= 0; 
  1173. }
  1174.  
  1175. inline int operator==(const SubString& x, const String& y) 
  1176. {
  1177.   return compare(y, x) == 0; 
  1178. }
  1179.  
  1180. inline int operator!=(const SubString& x, const String& y)
  1181. {
  1182.   return compare(y, x) != 0;
  1183. }
  1184.  
  1185. inline int operator>(const SubString& x, const String& y)      
  1186. {
  1187.   return compare(y, x) < 0;
  1188. }
  1189.  
  1190. inline int operator>=(const SubString& x, const String& y)     
  1191. {
  1192.   return compare(y, x) <= 0;
  1193. }
  1194.  
  1195. inline int operator<(const SubString& x, const String& y)      
  1196. {
  1197.   return compare(y, x) > 0;
  1198. }
  1199.  
  1200. inline int operator<=(const SubString& x, const String& y)     
  1201. {
  1202.   return compare(y, x) >= 0;
  1203. }
  1204.  
  1205. inline int operator==(const SubString& x, const SubString&  y) 
  1206. {
  1207.   return compare(x, y) == 0; 
  1208. }
  1209.  
  1210. inline int operator!=(const SubString& x, const SubString&  y)
  1211. {
  1212.   return compare(x, y) != 0;
  1213. }
  1214.  
  1215. inline int operator>(const SubString& x, const SubString&  y)      
  1216. {
  1217.   return compare(x, y) > 0;
  1218. }
  1219.  
  1220. inline int operator>=(const SubString& x, const SubString&  y)
  1221. {
  1222.   return compare(x, y) >= 0;
  1223. }
  1224.  
  1225. inline int operator<(const SubString& x, const SubString&  y) 
  1226. {
  1227.   return compare(x, y) < 0;
  1228. }
  1229.  
  1230. inline int operator<=(const SubString& x, const SubString&  y)
  1231. {
  1232.   return compare(x, y) <= 0;
  1233. }
  1234.  
  1235. inline int operator==(const SubString& x, const char* t) 
  1236. {
  1237.   return compare(x, t) == 0; 
  1238. }
  1239.  
  1240. inline int operator!=(const SubString& x, const char* t) 
  1241. {
  1242.   return compare(x, t) != 0;
  1243. }
  1244.  
  1245. inline int operator>(const SubString& x, const char* t)  
  1246. {
  1247.   return compare(x, t) > 0; 
  1248. }
  1249.  
  1250. inline int operator>=(const SubString& x, const char* t) 
  1251. {
  1252.   return compare(x, t) >= 0; 
  1253. }
  1254.  
  1255. inline int operator<(const SubString& x, const char* t)  
  1256. {
  1257.   return compare(x, t) < 0; 
  1258. }
  1259.  
  1260. inline int operator<=(const SubString& x, const char* t) 
  1261. {
  1262.   return compare(x, t) <= 0; 
  1263. }
  1264.  
  1265.  
  1266. // a helper needed by at, before, etc.
  1267.  
  1268. inline SubString String::_substr(int first, int l)
  1269. {
  1270.   if (first < 0 || (unsigned)(first + l) > length() )
  1271.     return SubString(_nilString, 0, 0) ;
  1272.   else 
  1273.     return SubString(*this, first, l);
  1274. }
  1275.  
  1276. #endif
  1277.